<!DOCTYPE html>
<html lang="zh">
<head>
	<meta charset="UTF-8">
	<base href="http://localhost/notebook/" />
	<title>《Java核心技术 卷I：基础知识(第八版）》（美.Cay S. Horstmann/Gary Cornell)</title>
	<link rel="stylesheet" type="text/css" href="./css/default.css" />
</head>
<body>
<article>
	<header>
		<h1>第1章 Java程序设计概述</h1>
		<section class="tips">
			<ul>
				<li>Java程序设计平台</li>
				<li>Java白皮书的关键术语</li>
				<li>Java和Internet</li>
				<li>Java发性简史</li>
				<li>关于Java的常见误解</li>
			</ul>
		</section>
	</header>
	<section>
		<p>Java是一个完整的平台，有一个庞大的库，包含了很多可重用的代码和一个提供诸如安全性、跨操作系统的可移植性以及自动垃圾收集等服务的执行环境。</p>
		<p>Java设计者编写了颇有影响力的白皮书，用来解释设计理念：</p>
		<ul>
			<li>简单性：是说其入门轻松，要想精通很难，类库太多了。运行环境很少，在哪儿都很好部署，不是指其学习曲线。</li>
			<li>面向对象：这种设技术把重点放在了数据和对象的接口上，先明确界面，再划分任务。Java不允许多重继承，但可以有多个接口，PHP也采用这种方式。不过，接口什么的我还没有用过。</li>
			<li>网络技能：Java能通过URL打开和访问网络上的对象，就像访问本地文件一样。当然，这都依赖于扩展类库。</li>
			<li>健壮性：去掉了指针等危险操作，编译器在编译时就可以检测出许多错误。</li>
			<li>安全性：为了实现其网络/分布式的目标，安全性很关键，但是它并不是决对安全</li>
			<li>体系结构中立：Java编译器通过生成与特定的计算体体系结构无关的字节码指令来实现这一特性。字节码可以很容易地在任何机器中解释执行。字节码的执行速度肯定比机器码慢，但是Java虚拟机可以将使用最频繁的字节码编译为机器码，这称为即时编译，很有效果。</li>
			<li>可移植性：它明确定义了一些概念，没有依赖环境的的地方，比如，Java中的数据类型具有固定的大小，int永远是32位整数，字符串用标准的unicode字符。</li>
			<li>解释型：任何有Java解释器的机器都可以运行Java字节码，甚至可以链接其他人的字节码。</li>
			<li>高性能：现在即时编译器性能已经很强了，也比较灵活。但是Java写的大型应用程序就是不够快。</li>
			<li>多线程：只要操作系统支持，Java就可以利用多个处理器。在多线程编程方面的简单性是Java成为服务器端开发语言的主要原因之一。</li>
			<li>动态性：在需要时可将代码添加到正在运行的程序中。</li>
		</ul>
		<p>在网页中运行的Java程序称为Applet。这种应用慢慢消失了，因为不同浏览器的解析也不一样。HTML5已经取消了applet标记。JavaScript是由已经不存在了的Netscape公司发明的，除了其语法类似于Java外，与Java没有任何关系。</p>
	</section>
	<footer>
		<p>这一章解释了Java的特点，以及什么是Java，什么不是。现在Android大行其道，Java作为Android的主要编程语言，应当很有前途。</p>
	</footer>
</article>
<article>
	<header>
		<h1>第2章 Java程序设计环境</h1>
		<section class="tips">
			<ul>
				<li>安装Java开发工具箱</li>
				<li>选择开发环境</li>
				<li>使用命令行工具</li>
				<li>使用集成开发环境</li>
				<li>运行图形化应用程序</li>
				<li>建立并运行applet</li>
			</ul>
		</section>
	</header>
	<section>
		<p>Java工具包术语，真多，真乱</p>
		<table>
			<tr><th>术语名</th><th>缩写</th><th>解释</th></tr>
			<tr><td>Java Development Kit</td><td>JDK</td><td>编写Java程序的程序员所使用的软件</td></tr>
			<tr><td>Java Runtime Environment</td><td>JRE</td><td>运行Java的用户使用的软件，包含虚拟机但不包含编译器</td></tr>
			<tr><td>Standard Edition</td><td>SE</td><td>用于桌面或简单服务器应用的Java平台</td></tr>
			<tr><td>Enterprise Edition</td><td>EE</td><td>用于复杂的服务器应用的Java平台</td></tr>
			<tr><td>Micro Edition</td><td>ME</td><td>用于手机或其它小型设备的Java平台</td></tr>
			<tr><td>Java 2</td><td>J2</td><td>一个过时的术语，用于描述1998年～2006年间的Java版本</td></tr>
			<tr><td>Software Development Kit</td><td>SDK</td><td>一个过时的术语，用于描述1998年～2006年间的JDK</td></tr>
			<tr><td>Update</td><td>u</td><td>用于发布修改的bug，如果软件被称为更新也不必担心，因为它包含了整个JDK最新版本。</td></tr>
			<tr><td>Netbeans</td><td>-</td><td>Sun的开发环境，Sun在2010年已被Oracle收购了</td></tr>
		</table>
		<p>Java只在安装和编译时与系统有关，在运行字节码时就是通用的了。javac是Java编译器，它将Java源代码文件编译为字节码。应当注意下面几点常识：</p>
		<ul>
			<li>源代码的文件名要与其中定义的public类名一致，在一个源文件中只能有一个公有类（可以有若干非公有类），而且是区分大小写的</li>
			<li>编译时要使用完整的文件名（带上扩展名.java），运行时只需要指定类名即可（不需要护展名）</li>
			<li>如果程序中的错误太多，可以用2>操作符，将错误重定向到一个文件中。</li>
		</ul>
		<p>Eclipse是用Java编写的，但是因为用的是非标准视窗类库，因此不如Java那样具备可移植性，因此，它需要针对不同操作系统发布专用版本。</p>
	</section>
	<footer>
		<p>这一章介绍了Java的编程环境，演示了Java代码。Android Studio是多么强的一个编程工具啊，可以自动导入类库！</p>
	</footer>
</article>
<article>
	<header>
		<h1>第3章 Java基本的程序设计结构</h1>
		<section class="tips">
			<ul>
				<li>一个简单的Java应用程序</li>
				<li>注释</li>
				<li>数据类型</li>
				<li>变量</li>
				<li>运算符</li>
				<li>字符串</li>
				<li>输入输出</li>
				<li>控制流程</li>
				<li>大数值</li>
				<li>数组</li>
			</ul>
		</section>
	</header>
	<section>
		<p>Java是大小写敏感的。应用程序的全部内容都必须放置在类中。凡是面向对象用到的类或变量等均用驼峰法命名，其它的使用下划线分割。源代码的文件名必须与公有类的名称相同，并用.java作为护展名。运行时，将从main方法开始执行，因此每个Java应用程序都必须有个main方法。根据Java规范，main方法必须声明为public。Java中的所有函数都属于某个类的方法，main方法必须有个外壳类，而且它必须是静态的。如果希望程序在退出时（退出main函数）返回其他的代码，就需要调用System.exit方法。</p>
		<p>以/**开始的是文档注释，用于自动生成文档。</p>
		<p>Java是一种强类型的语言，必须为每一变量声明一种类型。有四种整型数：int(4个字节-20亿~+20亿）/short(2字节）/long(8字节，最好在长整型数值后加个L）/byte（1字节）。两种浮点类型：float(4字节，有效位6～7位）/double（8字节，有效位15位），在需要小数的大多数情况下都应使用double类型，这也是小数的默认形式，如果要特别声明float常量需加后缀F，否则，即默认为D。Double类还有三个常量：Double.POSITIVE_INFINITY表正无穷大（一个正浮点数/0）；Double.NEGATIVE_INFINITY负无穷大；Double.NaN不是一个数字0/0或负数的平方根。浮点数不适用于出现舍入误差的计算，因为它采用二进制系统表示，是无法精确表示十分之一的。就好象十进制无法表示三分之一一样。char类型用于表示字符常量，除非要对UTF16代码单元进行操作，否则，不要使用char类型。Java中的boolean型不能与整型数相互转换，比如：在java中if(x=0)是错误的表达式，因为x=0不能转换为布尔值。</p>
		<p>Java中的字母包括除英文字母外，其他语言中表示字母的任何Unicode字符（反正也不认识和输入别国字母），并且变量名长度没有限制。一行一条声明语句可以提高程序的可读性。变量的声明尽量靠近它第一次使用的地方。</p>
		<p>Java中以final关键字声明常量，可以用static final设置一个类常量。整数除以0时会产生异常。如果将一个类标记为strictfp，那个此类中的所有方法都要使用严格的浮点计算。</p>
		<p>关系运算符&&/||按短路方式求值，靠左边的表达式即可得玏结果时，将不再计算右边的。</p>
		<p>Math类包含了各种各样的数学函数，这是一个静态类，不需要实例化可以直接使用。比如:求平方根Math.sqrt(x);而从JDK5.0 开始，已经不必在数学方法名和常量名前添加前缀Math.了，只需在文件顶部添加import static java.lang.Math.*;𢖻入即可。如果计算结果比速度更重要的话，就一定要选择Math类。</p>
		<p>在程序运行时，经常需要将一种数值类型转换为另一种类型。转换规则如下图所示，其中虚线箭头表示可能有精度损失的转换。</p>
		<img src="images/change_between_value_type.jpg" />
		<p>有时还需要由高到低将数据类型进行强制转换，比如，想对浮点数（x = 9.987）进行舍入运逄，以得到最近的整数。应当这样：(int)Math.round(x); Math.round返回的是长整型，因此，如果需要将它赋值给整型变量的话就要进行强制类型转换了。</p>
		<p>关于操作符运算顺序，最高的是[]以及对象中的方法调用，其次是自曾减、正负号及小括号，然后是四则运算，接下来是位移操作，随后是比较运算算中的大小比较，然后是比较运算符中的相等不等比较，跟着是二进制的&^|，然后是逻辑与，逻辑或，再接下来是三元运算符，最后进赋值运算符，包括右结合的赋值运算符。</p>
		<p>Java没有内置字符串类型，而是在类库中提供了一个预定义类String来处理字符串。Java中使用+来拼接字符串，如果非字符串与字符串一起进行+运算，则非字符串将转换为字符串。任何Java对象都可以转换为字符串。注意：Java的字符串不是数组，它不可以直接操作修改。</p>
		<p>要检测字符串相等，使用equals方法。比如：s.equals(t)；甚至可以直接用字符串常量调用此方法，比如："hello".equals(t);。注意：一定不能用==来比较两个字符串是否相等，它只对检测两个字符串是否在同一位置上。</p>
		<p>Java的数据类型是一个采用UTF-16编码表示的Unicode代码点的代码单元。辅助字符需要用一对代码单元表示，因此就有了两种长度：字符个数和代码点数量。</p>
		<p>Java包含许多方法和类，因此要全部记住是不可能的，必须学会使用在线文档。</p>
		<p>如果需要将多个字符串构成一个字符串时，应当使用字符串构建器，因为使用连接的话，每次都会构建一个新的String对象。字符串构建器使用方式如下：</p>
		<pre>
			StringBuilder string = new StringBuilder();		//创建字符串构建器
			string.addpend(str);		//在每次需要添加内容时，调用这个方法添加就可以了
			String completeString = string.toString();		//最后用toString方法得到String对象
		</pre>
		<p>从控制台输入需要读取标准输入流，首先要构建一个Scanner对象并将它与System.in关联。首先要引入java.util.*;然后如下定义Scanner in = new Scanner(System.in);这样，就可以用实例化的in来接收标准输入了。比如String name = in.nextLine();因为输入是可见的，不适合密码，所以Java SE 6特别引入了Concle类。</p>
		<p>Java的printf可以格式化输出，沿用了C语言的printf方法，它可用的转换符如下表：</p>
		<table>
			<tr><th>转换符</th><th>类型</th><th>举例</th><th>转换符</th><th>类型</th><th>举例</th></tr>
			<tr><td>d</td><td>十进制整数</td><td>159</td><td>s</td><td>字符串</td><td>Helllo</td></tr>
			<tr><td>x</td><td>十六进制整数</td><td>9f</td><td>c</td><td>字符</td><td>H</td></tr>
			<tr><td>o</td><td>八进制整数</td><td>237</td><td>b</td><td>布尔</td><td>True</td></tr>
			<tr><td>f</td><td>定点浮点数</td><td>15.9</td><td>h</td><td>散列码</td><td>42628b2</td></tr>
			<tr><td>e</td><td>指数浮点数</td><td>1.59e+01</td><td>tx</td><td>日期时间</td><td>参数表很表，用时再查吧</td></tr>
			<tr><td>g</td><td>通用浮点数</td><td>1.353232</td><td>%</td><td>百分号</td><td>%</td></tr>
			<tr><td>a</td><td>十六进制浮点数</td><td>0x1.fccdp3</td><td>n</td><td>与平台有关的行分隔符</td><td></td></tr>
		</table>
		<p>用于控制格式化输出的标志如下表：</p>
		<table>
			<tr><th>标志</th><th>目的</th><th>举例</th></tr>
			<tr><td>+</td><td>打印正数和负数的符号</td><td>+3.333</td></tr>
			<tr><td>空格</td><td>在正数这前添加空格</td><td>|  3.333|</td></tr>
			<tr><td>0</td><td>数字前面补0</td><td>003.333</td></tr>
			<tr><td>-</td><td>左对齐</td><td>|3.333  |</td></tr>
			<tr><td>(</td><td>将负数写在括号内</td><td>(3.333)</td></tr>
			<tr><td>,</td><td>添加数字分节符</td><td>3,333.333</td></tr>
			<tr><td>#（对于f格式）</td><td>包含小数点</td><td>3,333</td></tr>
			<tr><td>#（对于x或0格式）</td><td>添加前缀0x或0</td><td>0xcafe</td></tr>
			<tr><td>$</td><td>给定被格式化的参数索引。例如，%1$d, %1$x表示将以十进制和16进制格式打印第1个参数</td><td>159 9f</td></tr>
			<tr><td>&lt;</td><td>格式化前面说明的数值。例如，%d%&lt;x以十进制和十六进制打印同一个数值</td><td>159 9f</td></tr>
		</table>
		<p>格式说明符的语法如下：</p>
		<img src="images/format_specifiers.jpg" />
		<p>要对文件进行读取的话，需要用File对象构造Scanner对象，即把文件输入是：Scaner in = new Scanner(new File("myfile.txt"));如果要在文件名中加入路径，需要使用\进行转义，比如\\home\\ford。</p>
		<p>要写入文件则需要构建PrintWriter对象，PrintWriter out = new PrintWriter("myfile.txt");。注意：如果用一个不存在的文件名构造Scanner或用PrintWriter创建一个无法创建的文件将会产生比除以0更严重的异常，因此，应为此创建异常处理。</p>
		<p>不能在嵌套在代码块中声明同名变量。</p>
		<p>在Java的switch语句中，case标签必须是整数或枚举常量，不能用字符串，因为如前所述Java的字符串不能用逻辑操作符比较。</p>
		<p>Java的break语句可以指定标签，使break一下跳到标签定义（字符串：）的位置，但是只能跳出语句块，不能跳入。不管怎样，都不提倡这种方式。</p>
		<p>如果基本的整数和浮点精度不能满足要求，可以使用java.math包中的两人个很有用的类：BigInteger和BigDecimal。这两个类可以处理包含任意长度/精度的整数和浮点数的运算。但是不能用四则运算符，只能使用类中提供的方法。</p>
		<pre>
			import java.math.*;
			import java.util.*;

			public class BigIntegerTest
			{

				public static void main(String[] args)
				{
				Scanner in = new Scanner(System.in);

				System.out.println("How many number do you need to draw?");
				int k = in.nextInt();

				System.out.println("What is the highest number you can draw?");
				int n = in.nextInt();

				BigInteger lotteryOdds = BigInteger.valueOf(1);

				//下面计算n*(n-1)*(n-2)*(n-k+1)/1*2*3*...*k
				for(int i = 1; i <= k; i++)
				{
					lotteryOdds = lotteryOdds.multiply(BigInteger.valueOf(n - i + 1)).divide(BigInteger.valueOf(i));
				}

				System.out.println("Your odds are 1 in " + lotteryOdds + ". Good luck!");
				}

			}
		</pre>
		<p>声明数组的语法：数据类型[]数组名；或数据类型 数组名[];。数组初始化需要使用new，比如int a[] = new int[100];。如果直接以常量初始化数组，可以如此：int a[]={2,3,5,7}（注意，这里没有使用new）。还可以这样a = new int[]{17,19,23}</p>
		<p>Java SE 5.0增加了一个类似于foreach的循环：for(element:collection)，比如上例中：for(int e:a)System.out.println(e);，将打印数组a的每个元素。用这个打印数组不必担心下标，因此是个不错的方法。</p>
		<p>数组还有toString方法，可以将数组元素以逗号分割，放在方知号内并转换为字符串。</p>
		<p>可使用数组的copyOf方法来复制一个数组，这样，两个变量将指向同一数组。复制过程中可用第二个参数指定长度，如果新长度比以前更长，则多出的将赋值为0,如果短，则只拷贝前面的元素。</p>
		<p>main方法的String[] args参数用来接收命令行参数。Java实际上没有多维数组，而只有一维数组，多维数组在Java中称作数组的数组。多维数组一直没有机会用，感觉意义不大。</p>
	</section>
	<footer>
		<p>这一节学习了Java语言的基础，在编译的时候，出在包和路径的问题，后面要注意。</p>
	</footer>
</article>
<article>
	<header>
		<h1>第4章 对象与类</h1>
		<section class="tips">
			<ul>
				<li>面向对象程序设计概述</li>
				<li>使用现有类</li>
				<li>用户自定义类</li>
				<li>静态域和方法</li>
				<li>方法参数</li>
				<li>对象构造</li>
				<li>包</li>
				<li>类路径</li>
				<li>文档注释</li>
				<li>类设计技巧</li>
			</ul>
		</section>
	</header>
	<section>
		<p>封装，隐藏类的数据，只能通过对象的方法与对象数据进行交互，这是提高重用性和可靠性的关键。Java中所有的类均源自一个超类Object。</p>
		<p>首先从设计类开始，然后再往每个类中添加方法。系统中的名词一般可以单独成为一个类。在Java中对象变量与对象是不同的，如下Data birthday;这样只是定义了一个对象变量，并没有初始化，所以它不是个对象，不能当作对象操作。接下来 birthday = new Data()；用类给它初始化之后，它才成为一个对象。Date deadline = birthday;这样，定义了另一个对象引用同一个变量。变量不会自动初始化为null，必须要调用new或使用null将它们进行初始化。</p>
		<p>Java用来表示时间的类有两种，一种是完全的时间点类，即Date类，它用来表示时间，但不擅长处理日期。另一种是GregorianCalendar类及其扩展类Calendar类，它们描述了日历的一般属性，理论上，可以通过扩展Calendar类来实现中国的阴历或火星日历，但标准类库中只实现了Gregorian日历。注意：这个类中的月份是从0开始计数的，11表示12月。</p>
		<p>通常，最好使用不同的类表示不同的概念。比如前面Java对时间的处理。</p>
		<p>要创建一个完整的程序，应该将若干类组合在一起，其中只有一个类有main方法。这本书里编写类的风格是方法在前，域（类属性）在后面，以消减对实现的注意。</p>
		<p>如果习惯将每个类保存在一个单独的文件中，可以有两种编译方法：</p>
		<ul>
			<li>使用通配符，比如：javac Employee*.java，当然这样的前提是这些类具有相同的前缀（此处为Employee）</li>
			<li>直接编译public主类：javac EmployeeTest.java，这个类作为公有类，其中实例化了Employee类。编译器会自动查找名为Employee.class的文件，如果没有就会找Employee.java并编译。可以认为javac内置了make编译功能。</li>
		</ul>
		<p>再次提醒：为了确保类的封装，应将属性都设为private，不要在类之外直接操作类的属性。</p>
		<p>Java的构造器有以下特点：</p>
		<ul>
			<li>构造器与类同名</li>
			<li>每个类可以有一个以上构造器</li>
			<li>构造器可以有0个、或若干个参数</li>
			<li>构造器没有返回值</li>
			<li>构造器总是伴随着new操作一起调用，它不能被实例直接调用比如：不可以使用employee.Employee()来调用构造器</li>
			<li>不要在构造器中定义与类属性同名的变量，因为，它们将屏蔽类的属性。</li>
			<li>不要让类的方法直接返回对象变量，因为对象采用引用传递，因此为破坏封装性。如果确需返回对象，应当使用克隆，比如return (Date)hireDay.clone();</li>
		</ul>
		<p>一个方法可以访问所属类的所有对象的私有数据。比如：return name.equals(otherEmployee.name);。</p>
		<p>类中的辅助方法，在类调用的方法，应当设置为private类型。只要方法是私有的，就可以确信其它类中不会有对它的调用，可以随便删除。</p>
		<p>类的属性可以设置为final属性，这种属性必须在类实例化时初始化，并且不允许被改变（即不要写setValue方法），但是并不是说这类属性就一定是，因为对于非可变类（比如Sting)或基本数据类型的属性，没有其它改变方法，是可以作为常量看待的，而对于Date这种可变类属性，即变在类中没有修改值的方法，也可以通过Date类的方法来修改它的值。</p>
		<p>static静态属性，也称为类属性，所有类实例共享一个静态属性，而且它必须在类内部定义时就进行初始化，不用等类被实例化即可用类名调用。静态变量属性用的较少，比较多的是静态常量。Java常用的System.out即是一个静态常量，表示标准输出。自定义静态常量使用static final来定义，但是只限于基本数据类型和非可变类。</p>
		<p>静态方法：不能向对象实施操作的方法。比如Math类的pow方法。静态方法不能操作对象，需要直接用类名来调用这类方法。虽然也可以用对象来调用静态方法，但因为这样容易引起混淆，所以不建议。如果一个方法不需要访问对象状态或只需要访问类的静态属性时就应当将其定义为静态方法。</p>
		<p>main方法不对任何对象进行操作，事实上在启动程序时还没有任何一个对象。静态的main方法将执行并创建程序所需的对象。而且，每个类都可以有一个main方法，这是对象进行单元测试的常用办法。即使是非入口类也可以有main方法，只是作为应用程序的一部分它永远不会被执行而已。比如下面的示例EmployeeTest.java：</p>
		<pre>
			import java.util.*;


			public class EmployeeTest
			{
				public static void main(String[] args)
				{
					Employee[] staff = new Employee[3];

					staff[0] = new Employee("Call Cracker", 75000D, 1987, 12, 15);
					staff[1] = new Employee("Harry Hacker", 5000, 1989, 10, 1);
					staff[2] = new Employee("Tony Tester", 40000, 1990, 3, 15);

					for(Employee e : staff)
					{
						System.out.println("name=" + e.getName() + ", Salary=" + e.getSalary() + ", hireDay=" + e.getHireDay());
					}
				}

			}

			class Employee
			{
				public Employee(String stringName, double doubleSalary, int intYear, int intMonth, int intDay)
				{
					name = stringName;
					salary = doubleSalary;
					GregorianCalendar calendar = new GregorianCalendar(intYear, intMonth-1, intDay);
					hireDay = calendar.getTime();
				}

				public String getName()
				{
					return name;
				}

				public double getSalary()
				{
					return salary;
				}

				public Date getHireDay()
				{
					return hireDay;
				}

				public void raiseSalary(double byPercent)
				{
					double raise = salary * byPercent/100;
					salary += raise;
				}

				/**
				 * 下面这个只能用于Employee类的独立测试，在EmployeeTest程序中永远不会被执行。
				 * @param args
				 */
				public static void main(String[] args)
				{
					Employee e = new Employee("Harry", 50000, 1982, 5, 1);
					System.out.println(e.getName() + " " + e.getSalary());
				}

				private String name;
				private double salary;
				private Date hireDay;


			}
		</pre>
		<p>如上面的定义，在执行javac EmployeeTest.java进行编译后，将产生两个class文件，因为Employee类有static main函数，就可以用java Employee对其进行独立测试，但是在执行java EmployeeTest时，Employee的main方法永远不会被执行。</p>
		<p>Java函数的方法总是采用传值调用，方法得到的是一所有参数值的一个拷贝，它不能修改传递给它的任何参数变量的内容。但是以对象作为参数就不同了，对象参数虽然也是以值传递，但是在由函数中得到的却是对象的引用，因此，对象的值会发生改变。</p>
		<ul>
			<li>方法不能修改一个基本数据类型参数（即数值型和布尔型）</li>
			<li>方法可以改变一个对象参数的状态</li>
			<li>方法不能实现让对象参数引用一个新的对象</li>
		</ul>
		<p>Java类可以有多个构造器，只需重载构造方法即可。有相同的名字不同的参数就产生了重载。要完整的描述一个方法，需要说明方法名和参数类型列表，这称为函数署名，不能存在两人个署名相同的函数。如果不在构造器中为属性赋值，那将会自动地赋为默认值数值为0,布尔值为false，对象引用为null。应当尽量在初始化时为属性赋值。如果想在初始化一个对象时不进行任何赋值，需要定义一个参数表为空的构造器。</p>
		<p>在定义方法的参数名时，不要和类的属性名重复，否则在方法中使用的将是参数变量，而不是类的属性，要想在方法中调用类的属性的话，需要用this引用。</p>
		<p>还可以在一个构造器中用this调用另一个构造器，如下：</p>
		<pre>
			public Employee(doiuble s)
			{
				this("Here is another", s)
			}
		</pre>
		<p>Java还可以用初始化块对类进行初始化。即在类定义中一段用大括号括起来的赋值语句，这样的语句一般要放在类属性的定义之后，这些语句无论用什么构造器构造，它们都会被先于构造方法执行。下面是调用构造器的步骤：</p>
		<ol>
			<li>所有属性被初始化为默认值（0、false、null）</li>
			<li>按照在类声明中出现的次序，依次执行所有属性的初始化语句和初始化块</li>
			<li>如果构造器第一行调用了第二个构造器，则执行第二个构造器主体</li>
			<li>执行这个构造器的主体</li>
		</ol>
		<p>Java没有析构函数，因为它有自己的垃圾回收机制。如果某个类在使用完毕后要立刻关闭，需要代码来调用其dispose或close方法来完成清理操作。</p>
		<p>Java允许用户使用包将类管理起来，标准的Java类库分布在多个包中，包括java.lang，java.util和java.net等。一个类可以使用所属包中的所有类，以及其他包中的公有类。有两种方式访问其它包的公有类：1、使用包名.类名;2、用import导入其它类或包含其它类的整个包。如果两个包中有命名冲突的时候就只能用第一种方式了。</p>
		<p>如果引入的两个包中有相同名称的类且都需要使用，就只能用各自的全名来引用了。从Java SE5.0开始，import语句增加了导入类的静态方法和静态域的功能。如在import后加入static关键字（注意，只能用于类或类的方法及属性的导入），就可以使用所导入类的静态方法和静态属性，而不用加类名前缀了。这种方式不利于代码的清晰度，仅在需要使用数学函数或笨重的常量时采取这种方法比较合适。</p>
		<p>要想将一个类放入包中，就必须将包的名字放在源文件的开头，在定义类的代码之前，如果不使用package关键字，那么类将属于default package。包中的文件位置也必须与包名匹配。</p>
		<p>为了使类能够被多个程序共享，可以将类放于一个目录中，或者是打包压缩的jar类文件中（zip格式)。如果采用后者，需要在包含路径中指定包文件的全名。如果只是在编译时需要引用额外的类，可以使用在编译时使用带classpath参数的编译指令，比如：java -classpath &lt;需要包含的类路径&gt; MyProg.java</p>
		<p>JDK包含一个利用代码注释生成文档的工具——javadoc。应当为包/公有类与接口/公有的和受保护的方法/公有的和受保护的变量编写注释，注释以/**开始，以*/结束。注释标记内使用的是自由标记文本，即由@开始的一系列变量，如@author或@param等。自由格式文本的第一句应庐是概要性的名子，javadoc自动将这些句子抽取出来形成概要页。在自由格式文本中可以使用HTML标记，不过不要使用hr和h1，因为它们会与文档的格式冲突。如果有些额外的文件需要链接到注释中，可放在doc-files目录下。类注释必须放在import语句之后，类定义之前。</p>
		<p>使用@see可以插入引用的超链接。比如：@see com.horstmann.corejava.Employee#raiseSalary(double)即生成一个指向Empoyee类中raiseSalary文档的链接。如果不用类名，则是会引用当前包的当前类。也可以在@see后使用HTML的a标签引入任何链接。如果@see后是双引号，文本就会会显示在see also部分。如果愿意的话，可以在注释中的任何位置插入指向其它类的超链接或个人专用标记：{@link package.class#feature label}</p>
		<p>如果要为整个包生成单独的注释：-需要在每一个包目录中添加名为package.html的文件，这个文件中body标签中间的内容都会被抽取出来；-还需要提供一个名为package-info.java的文件，包含一个以/**和*/界面的javadoc注释，跟随在package语句之后，此外，它不应该包括更多的注释或代码。如果要为所有源文件提供注释，可以写在名为overview.html的文件中。</p>
		<p>在用javadoc生成文档时，应当用-d参数指定文档所在目录，否则会在当前目录下生成所有文档。此外，还可用doclite生成其它格式的文档。</p>
		<p>类的设计技巧</p>
		<ul>
			<li>一定将数据设计为私有,绝对不要破坏封装性</li>
			<li>一定要对数据初始化</li>
			<li>不要在类中使用过多的基本数据，比如用一个Address类替换用于描述地址的多个基本数据</li>
			<li>不是所有属性都需要独立的访问方法或更改方法</li>
			<li>使用标准格式进行类定义：一般采用如下顺序写类的内容-公有访问特性，包作用域访问特性，私有访问。每一部分中按以下顺序书写-实例方法，静态方法，实例属性，静态属性</li>
			<li>将职责过多的类进行分解</li>
			<li>类名和方法名要能体现它们的职责</li>
		</ul>
	</section>
	<footer>
		<p></p>
	</footer>
</article>
<article>
	<header>
		<h1>第5章 继承</h1>
		<section class="tips">
			<ul>
				<li>类、超类和子类</li>
				<li>Object：所有类的超类</li>
				<li>泛型数组列表</li>
				<li>对象包装器和自动打包</li>
				<li>参数数量可变的方法</li>
				<li>枚举类</li>
				<li>反射</li>
				<li>继承设计的技巧</li>
			</ul>
		</section>
	</header>
	<section>
		<p>继承已存在的类就是复用这些类的方法和属性。反射是指在程序运行期间发现更多的类及其属性的能力。定义继承类的一个原则是用"is a“方法，比如，如果经理是一个雇员，就可以定义经理类为雇员类的子类。一个父类变量是可以用来引用子类对象的，即可以把子类对象赋值给父类对象变量，但是反之不行。当然，父类变量即便被赋予子类对象的值，也只可以使用父类中有的方法和属性。</p>
		<p>对象方法的执行过程：</p>
		<ol>
			<li>在调用一个类的方法时，编译器会列出类跟超类中所有访问属性为public的方法。</li>
			<li>接下来，编译器开始查看调用方法时提供的参数表，如果找不到名称与参数表完全匹配的方法就会告错，找到则执行。</li>
			<li>如果是private/static/final方法或者构造函数，那么编译器可以准确地知道应该调用哪个方法。这种调用方式称为静态绑定。</li>
			<li>如果子类中覆盖了父类的方法，则会执行子类方法，如果没有，则执行父类方法。</li>
		</ol>
		<p>籽了优化执行速度，Java虚拟机预先为每个类创建了一个方法表，这样，在真正调用方法的时候，虚拟机仅查找这个表就可以了。在覆盖一个方法的时候，子类方法的可见低不能低于超类中的。</p>
		<p>要阴止类或方法被继承，可在定义时使用final关键字。如果将一个类定义为final，那么只有其中的方法自动具有final属性，其属性则不具备final属性。</p>
		<p>强制类型转换，感觉这个东西没有什么存在的必要，大概是为了保持语法的完整性吧。</p>
		<p>抽象类：包含一个或多个abstract方法的类必须被声明为抽象类。抽象类不可被实例化，只能被继承。类即使不含有抽象方法，也可以被声明为抽象类。</p>
		<p>最好将类中的属性标记为private而方法标记为public。如果希望子类能访问超类中的某个属性或方法，而拒绝其它类访，可将其声明为protected。尽量不要使用这个关键字，因为它破坏了类的封装。</p>
		<p>Object类-所有类的超类，因此可以使用Object的对象引用任何类的对象。这个好象也没什么意义。Equals方法：这是Object类中的方法，用于检测一个对象是否等于另外一个对象。对象进行比较，有必要么？Object类定义了hashCode方法，用来计算散列码。Object还定义了toString方法用于将类转换为字符串显示。建议为每个类增加toString方法。</p>
		<p>ArrayList是一个采用类型参数的范型类，为了指定数组列表保存的元素对象类型需要用一对尖括号将类名括起来加在后面（注意，尖括号不能用于基本数据类型，只能用类名），比如，ArrayList&lt;Employee&gt;，要构造一个ArrayList可以象这样：ArrayList&lt;Employee&gt; staff = new ArrayList&lt;Employee&gt;();。使用ArrayList的add方法可以将元素添加到数组列表中。如staff.add(new Employee("harry", ....);。ArrayList类并不是Java语言的一部分，它是由程序员编写并被放入了标准库中的一个实用类。要获得/改变其中的元素需要使用get/set方法。比如staff.set(i, harry)；将harry对象赋值给staff列表的第i的元素。</p>
		<p>所有基本数据类型都有与之对应的类，比如int对应的类是Integer，还有Long/Float/Double/Short/Byte/Charater/Void/Boolean等类。这些类是不可变的，一旦实例化后，就不许更改其中的值。将一个基本类型值赋予它所对应的类变量时，会有一个自动打包的过程。比如：Integer i = 3；后台将会执行的是i= new Integer(3);,</p>
		<p>Java SE 5.0之后支持可变参函数。只需要参数的类型和参数名之间加入三个.号即...即可，比如:public double max(double ... values)，这样定义的函数可以接受任意多个参数，用逗号分割即可。</p>
		<p>所有枚举类型都是Enum类的子类，比较两个枚举类型的值时，要用==而不是equals方法。如果需要的话，可以在枚举类型中添加构造器、方法和类。比如：</p>
		<pre>
			enum Size
			{
				private String abbreviation;

				SMALL("S"), MEDIUM("M"), LARGE("L"), EXTRA_LARGE("XL");

				private Size(String abbreviation)
				{
					this.abbreviation = abbreviation;
				}

				public String getAbbreviation()
				{
					return abbreviation;
				}
			}
		</pre>
		<p>能够分析类能力的程序被称为反射（reflective），它具有：</p>
		<ul>
			<li>在运行中分析类的能力</li>
			<li>在运行中查年对象，例如，编写一个toString方法供所有类使用</li>
			<li>实现数组的操作代码</li>
			<li>利用Method对象，这个对象很象C++中的函数指针</li>
		</ul>
		<p>反射功能强大且复杂，使用它的主要对象是工具构造者，而不是程序员，如果对构造工具不感兴趣，跳过。Java运行时会为所有的对象保存其所属的足迹，称作运行时信息，虚拟机利用运行时信息选择相应的方法执行。可以通过专门的Java类Class来访问这些运行时信息。</p>
		<p>继承设计的技巧：</p>
		<ol>
			<li>将公共操作和属性放在超类</li>
			<li>不要使用protected属性</li>
			<li>使用继承实现“is-a”关系</li>
			<li>除非所有继承的方法都有意义，否则不要使用继承</li>
			<li>在覆盖方法时，不要改变预期的行为</li>
			<li>使用多态，而非类型信息</li>
			<li>不要过多地使用反射</li>
		</ol>
	</section>
	<footer>
		<p></p>
	</footer>
</article>
<article>
	<header>
		<h1>第6章 接口和内部类</h1>
		<section class="tips">
			<ul>
				<li>接口</li>
				<li>对象克隆</li>
				<li>接口与回调</li>
				<li>内部类</li>
				<li>代理</li>
			</ul>
		</section>
	</header>
	<section>
		<p>接口不是类，而是对类的一组需求描述，这些类要遵从接口描迷的统一格式进行定义。接口中所有方法都自动的为public，因此国，在定义接口时不需要用使用public关键字。接口中还可以定义常量，但是接口不能含有实例属性，也不能实现方法。</p>
		<p>定义接口时，使用interface关键字，类似于抽象类的定义。要让类实现一个接口，使用implements关键字。接口不是类，不用实例化。一个类可以实现多个接口，这为定义类的行为提供了很大的灵活性。由于Java类只能拥有一个父类，因此，加入了接口的概念以完善类的设计。</p>
		<p>要拷贝一个对象，可以通过实现Cloneable接口，就可以使用Object类中的clone方法来实现对象的拷贝。因为默认的变量拷贝为引用同一个对象的两个变量，因此要得到两个不同实例，只能用clone方法。实现Cloneable接口，只是作为一个标记，表明类要进行克隆处理。</p>
		<p>回调，用来指出某个特定事件发生时应该采取的动作。比如按下鼠标或某个菜单项时应采取什么行动。这时，将一个定义好了执行动作的对象（这类对象，一般应实现监听事件所需要的接口比如ActionListener，而在实例化时，应当以接口来初始化并传递，因为监听事件不能识别到自定义类）传递给监听方法。</p>
		<p>内部类，是定义在另一个类内部的类。使用内部类有以下三个原因：</p>
		<ul>
			<li>内部类可以访问它所在作用域中的数据，包括私有数据</li>
			<li>内部类可以对同一个包中的其它类隐藏起来</li>
			<li>当想要定义一个回调函数，切不想编写大量代码时，使用匿名（anonymous)内部类比较便捷</li>
		</ul>
		<p>内部类可以直接调用外部类中的属性和方法。在外围类的作用域之外，可以这样来引用内部类：OuterClass.InnerClass。内部类是一种编译器现象，与虚拟机无关。编译器会把内部类翻译成以$分开外部类和内部类名的class文件，比如：TalkingClock$TimePrinter.class。</p>
		<p>局部类，如果某个类仅用于一个方法，可以将类定义到该方法内部，称为局部内部类。这种类不能用public或private访问符声明，它的作用域被限定于声明这个局部类的块中。对外部来说，一个局部类可以完全的被隐藏起来。</p>
		<p>匿名内部类，如果一个类仅使用一次，就可以将其作为内部类，如果只创建定个类的一个对象，那个类名也可以不要了。于是，就有了下面这种语法（真折腾）：</p>
		<pre>
			public void start(int interval,m final boolean beep)	//这一行加入final参数，是为了在其它地方也可以引用此参数
			{
				ActionListener listener = new ActionListener()	//*注
					{			//这儿定义一个匿名内部类
						public void actionPerformed(ActionEvent event)
						{
							Date now = new Date();
							System.out.println("At the tone, the time is " + now);
							if(beep) Toolkit.getDefaultToolkit().beep();
						}
					};
				Timer t = new Timer(interval, listener);
				t.start();
			}
		</pre>
		<p>*注：上面代码的含义是，创建一个实现ActionListener接口的类的新对象，需要实现的方法actionPerformed写在括号内。</p>
		<p>上面的代码等价于下面这种方式：</p>
		<pre>
		public void start()
		{
			ActionListener listener = new TimePrinter();
			Timer t = new Timer(interval, listener);
			t.start();
		}

		public class TimePrinter implements ActionListener
		{
			public void actionPerformed(ActionEvent event)
			{
				Date now = new Date();
				System.out.println("At the tone, the time is " + now);
				if(beep) Toolkit.getDefaultToolkit().beep();
			}
		}
		</pre>
		<p>如果在实例化一个类时，构造函数名的后面跟一对花括号，那么定义的就是匿名内部类。</p>
	</section>
	<footer>
		<p>结束第六章，有一些让人头疼的东西了，匿名内部类（这个在Android事件响应编程中大量用到要想明白），代理（这个概念感觉没什么意义，用到的地方也很少，略过）。</p>
	</footer>
</article>
<article>
	<header>
		<h1>第7章 图形程序设计</h1>
		<section class="tips">
			<ul>
				<li>Swing概述</li>
				<li>创建框架</li>
				<li>框架定位</li>
				<li>在组件中显示信息</li>
				<li>2D图形</li>
				<li>颜色</li>
				<li>字体</li>
				<li>图像</li>
			</ul>
		</section>
	</header>
	<section>
		<p>Swing没有完全替代AWT（Abstract Window Toolkit），而是基于AWT架构之上。它提供了引大的用户界面组件，指用户界面类，而AWT则是指像事件处理这样的窗口工具箱的底层机制。设计Swing组件的绘制方式是一个很繁琐的过程.Eclispe使和了一种与AWT类似，被称之为SWT的工具箱，可以映射到不同平台的本地组件上。除此之外，大多数Java用户界面程序设计使用的都是Swing。</p>
		<p>Swing类位于javax.swing包中，javax表示它是一个Java扩展包而不是核心包。在Swing程序中有两点技术需要强调：</p>
		<ol>
			<li>首先，所有Swing组件必须由事件调度线程进行配置，线程将鼠标点击和键盘敲击控制转移到用户接口组件。</li>
			<li>其次，定义一个用户关闭这个框架时的响应动作，因为在swing中用户关闭窗口时只是将其隐藏起来，并没有终止程序。</li>
		</ol>
		<p>简单的框架是不会自动显示出来的，因此，可以在让它第一次显示之前给它添加组件。在初始化语句结束后，main方法退出，但并没有终止程序，终止的只是主线程，事件调度线程仍处于激活状态，直到关闭框架或调用System.out.exit方法终止程序。Swing库负责绘制框架内的所有内容，也可以调用frame.setUndecorated(ture)来关闭所有框架装饰。JFrame类本身只包含若干个改变框架外观的方法，其它处理框架大小和位置的方法是由超类继承而来。主要有以下几个：</p>
		<ul>
			<li>setLocation(x,y)和setBounds(x,y,width,height)方法：设置框架位置</li>
			<li>setIconImage：定义标题栏、任务切换窗口等显示的图标</li>
			<li>setTitle：定义标题栏文字</li>
			<li>setResizeable：是否允许用户改变窗口大小</li>
		</ul>
		<p>由于Java文档仅对类本身定义的方法做解，因此，继承得来的方法需要查看超类API文档。AWT和Swing中框架和组件类的继承层次如下图：</p>
		<img src="./images/JFrameClass.png" />
		<p>框架中设置/读取属性的方法都是成对出现，比如有setTitle()方法就有getTitle()方法，而对于boolean属性则和is开头，比如：isLocationByPlatform()。</p>
		<p>JFrrame共有四层面板，根面板、层级面板和玻璃面板用来组织菜单栏和内容窗格以及实现观感。内容窗格最为重要，如下图所示：</p>
		<img src="./images/JFrameStructure.png" />
		<p>要把消息添加到窗口中，需要先绘制一个组件，扩展一个JComponent类（更多人喜欢用Jpanel类，因为JPanel本身也是可包含 其它组件的容器，而且也可在其上绘制，与部件不同的是，它不透明，这意味着要在它的边界面绘制所有的象素，常用的方式是使用super.paintComponent来用其父元素的背景色绘制它的背景），并覆盖其中的paintComponent方法，这个方法在应用程序需要重新绘图的时候会被自动调用，一定不要人为调用。如果需要强制刷新屏幕只需调用repaint方法。在Java中所有的绘制都必须使用Graphics对象，其中包含了绘制图案、图像和文本的方法。</p>
		<p>在Java中使用2D图形类库，通过调用paintComponent方法得到一个Graphics2D类对象。要绘制图形，首先要创建一个实现了Shape接口的类的对象，然后调用Grphoics2D中的draw方法。Java 2D图形类采用的是浮点数(Java会解释为double类型)坐标。注意：Java默认的浮点数是double类型，比如：float f=1.2;这条语句无法通过编译，应当写成double f=1.2或float f=1.2f;。这样就可以理解下面的语句了：</p>
		<pre>
			Rectangle2D r = ...;
			float f = (float)r.getWidth;	//此处要进行类型转换
		</pre>
		<p>为了淡化上面的这种不便，Java为Rectangle2D设计了两个内部类，Rectangle2D.float和Rectangle2D.double。直接使用double类型就行了，何必有float。</p>
	</section>
	<footer>
		<p></p>
	</footer>
</article>
<article>
	<header>
		<h1>第8章 事件处理</h1>
		<section class="tips">
			<ul>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
			</ul>
		</section>
	</header>
	<section>
	</section>
	<footer>
		<p></p>
	</footer>
</article>
<article>
	<header>
		<h1>第9章 Swing用户界面组件</h1>
		<section class="tips">
			<ul>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
			</ul>
		</section>
	</header>
	<section>
	</section>
	<footer>
		<p></p>
	</footer>
</article>
<article>
	<header>
		<h1>第10章 部署应用程序和Applet</h1>
		<section class="tips">
			<ul>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
			</ul>
		</section>
	</header>
	<section>
	</section>
	<footer>
		<p></p>
	</footer>
</article>
<article>
	<header>
		<h1>第11章 异常、日志、断言和调试</h1>
		<section class="tips">
			<ul>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
			</ul>
		</section>
	</header>
	<section>
	</section>
	<footer>
		<p></p>
	</footer>
</article>
<article>
	<header>
		<h1>第12章 泛型程序设计</h1>
		<section class="tips">
			<ul>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
			</ul>
		</section>
	</header>
	<section>
	</section>
	<footer>
		<p></p>
	</footer>
</article>
<article>
	<header>
		<h1>第13章 集合</h1>
		<section class="tips">
			<ul>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
			</ul>
		</section>
	</header>
	<section>
	</section>
	<footer>
		<p></p>
	</footer>
</article>
<article>
	<header>
		<h1>第14章 多线程</h1>
		<section class="tips">
			<ul>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
			</ul>
		</section>
	</header>
	<section>
	</section>
	<footer>
		<p></p>
	</footer>
</article>
</body>
</html>